package com.melodyframe.stage.core.performer;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import com.melodyframe.common.context.Context;
import com.melodyframe.common.context.loader.ContextLoader;
import com.melodyframe.common.context.loader.ContextRequest;
import com.melodyframe.stage.core.constants.CoreContextConstants;

public class BeanProxyPerformer implements Performer {

	private List<ContextRequest<?>>	paramaterRequests;

	private Method					method;

	private Object					bean;

	@SuppressWarnings("rawtypes")
	@Override
	public void perform(Context context) throws Exception {
		Object returnValue = null;
		if (null != paramaterRequests) {
			List<Object> paramaters = ContextLoader.load(context,
					paramaterRequests);
			returnValue = this.method.invoke(this.bean, paramaters.toArray());
		} else {
			returnValue = this.method.invoke(this.bean);

		}
		if (null != returnValue) {
			if (returnValue instanceof Result) {
				this.mergeResult((Result) returnValue, context);
			} else if (returnValue instanceof Map) {
				this.mergeResultContext((Map) returnValue, context);
			} else if (returnValue instanceof String) {
				this.mergeResultAction((String) returnValue, context);
			}
		}
	}

	private void mergeResult(Result result, Context context) {
		String resultAction = result.getAction();
		if (null != resultAction) {
			this.mergeResultAction(resultAction, context);
		}
		@SuppressWarnings("rawtypes")
		Map resultContext = result.getContext();
		if (null != resultContext) {
			this.mergeResultContext(resultContext, context);
		}
	}

	private void mergeResultAction(String resultAction, Context context) {
		context.put(CoreContextConstants.ACTION, resultAction);
	}

	private void mergeResultContext(
			@SuppressWarnings("rawtypes") Map resultContext, Context context) {
		for (Object key : resultContext.keySet()) {
			context.put(key.toString(), resultContext.get(key));
		}
	}

	public List<ContextRequest<?>> getParamaterRequests() {
		return paramaterRequests;
	}

	public void setParamaterRequests(List<ContextRequest<?>> paramaterRequests) {
		this.paramaterRequests = paramaterRequests;
	}

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public Object getBean() {
		return bean;
	}

	public void setBean(Object bean) {
		this.bean = bean;
	}

}
